#ifndef SANGAME_BASE_STRING_H_
#define SANGAME_BASE_STRING_H_

#include "base/base.h"

namespace sangame {
namespace base {

class AnsiString {
public:
    typedef std::string Type;

};

class Utf8String {
public:
    typedef std::string Type;

};

class UnicodeString {
public:
    typedef std::wstring Type;
};

template<class Dest, class Source>
typename Dest::Type string_cast(const typename Source::Type& source);

template<>
UnicodeString::Type string_cast<UnicodeString, AnsiString>(const AnsiString::Type& ansi_string)
{
	std::wstring result;

	int len = ::MultiByteToWideChar(CP_ACP, 0, ansi_string.c_str(), -1, NULL, 0)+20;
	wchar_t* buf = new wchar_t[len];
	memset(buf,0,len*sizeof(wchar_t));

	::MultiByteToWideChar(CP_ACP, 0, ansi_string.c_str(), -1, buf, len);
	result = buf;

	delete[] buf;
	return std::move(result);
}

template<>
AnsiString::Type string_cast<AnsiString, UnicodeString>(const UnicodeString::Type& unocode_string)
{
	std::string result;

	int len = WideCharToMultiByte(CP_ACP, 0, unocode_string.c_str(), -1, NULL, 0, NULL, NULL)+20;
	char* buf = new char[len];
	memset(buf,0,len);

	::WideCharToMultiByte (CP_ACP, 0, unocode_string.c_str(), unocode_string.size(), buf, len, NULL,NULL);
	result = buf;

	delete[] buf;
	return std::move(result);
}

template<>
UnicodeString::Type string_cast<UnicodeString, Utf8String>(const Utf8String::Type& utf8_string)
{
	std::wstring result;

	int len = ::MultiByteToWideChar(CP_UTF8, 0, utf8_string.c_str(), -1, NULL, 0)+20;
	wchar_t* buf = new wchar_t[len];
	memset(buf,0,len*sizeof(wchar_t));

	::MultiByteToWideChar(CP_UTF8, 0, utf8_string.c_str(), -1, buf, len);
	result = buf;

	delete[] buf;
	return std::move(result);
}

template<>
Utf8String::Type string_cast<Utf8String, UnicodeString>(const UnicodeString::Type& unicode_string)
{
	std::string result;

	int len = WideCharToMultiByte(CP_UTF8, 0, unicode_string.c_str(), -1, NULL, 0, NULL, NULL)+20;
	char* buf = new char[len];
	memset(buf,0,len);

	::WideCharToMultiByte (CP_UTF8, 0, unicode_string.c_str(), unicode_string.size(), buf, len, NULL,NULL);
	result = buf;

	delete[] buf;
	return std::move(result);
}

template<>
Utf8String::Type string_cast<Utf8String, AnsiString>(const AnsiString::Type& ansi_string)
{
	UnicodeString::Type unicode_string = string_cast<UnicodeString, AnsiString>(ansi_string);
	return std::move(string_cast<Utf8String, UnicodeString>(unicode_string));
}

template<>
AnsiString::Type string_cast<AnsiString, Utf8String>(const Utf8String::Type& utf8_string)
{
	UnicodeString::Type unicode_string = string_cast<UnicodeString, Utf8String>(utf8_string);
	return std::move(string_cast<AnsiString, UnicodeString>(unicode_string));
}

template<class T>
std::vector<typename T::Type> split(const typename T::Type& text, const typename T::type& token) {
	std::vector<typename T::Type> result;
	boost::split(result, text, boost::is_any_of(token));
	return std::move(result);
}

template<class Dest, class Source>
typename Dest::Type to_string(const Source& source)
{
	return std::move(lexical_cast<typename Dest::Type>(source));
}

} // namespace base
} // namespace sangame

#endif // SANGAME_BASE_STRING_H_